/*
 */

package beans;

import db_connect.DB;
import java.sql.Connection;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.http.HttpSession;

/**
 *
 * @author Milan Boricic <boricic@gmail.com>
 */
public class Rezervacija {
    private Integer rid;
    private Sala sala;
    private Korisnik korisnik;
    private String namena;
    private Date datum;
    private Timestamp datumRezervisanja;
    private Time pocevOd;
    private Integer trajanje;

    private String datumString;
    private String pocevOdString;

    public Rezervacija() {}
    
    public Date getDatum() {
        return datum;
    }

    public void setDatum(Date datum) {
        this.datum = datum;
    }

    public Timestamp getDatumRezervisanja() {
        return datumRezervisanja;
    }

    public void setDatumRezervisanja(Timestamp datumRezervisanja) {
        this.datumRezervisanja = datumRezervisanja;
    }

    public Korisnik getKorisnik() {
        return korisnik;
    }

    public void setKorisnik(Korisnik korisnik) {
        this.korisnik = korisnik;
    }

    public String getNamena() {
        return namena;
    }

    public void setNamena(String namena) {
        this.namena = namena;
    }

    public Time getPocevOd() {
        return pocevOd;
    }

    public void setPocevOd(Time pocevOd) {
        this.pocevOd = pocevOd;
    }

    public Integer getRid() {
        return rid;
    }

    public void setRid(Integer rid) {
        this.rid = rid;
    }

    public Sala getSala() {
        return sala;
    }

    public void setSala(Sala sala) {
        this.sala = sala;
    }

    public Integer getTrajanje() {
        return trajanje;
    }

    public void setTrajanje(Integer trajanje) {
        this.trajanje = trajanje;
    }

    public String getDatumString() {
        return datumString;
    }

    public void setDatumString(String datumString) {
        this.datumString = datumString;
    }

    public String getPocevOdString() {
        return pocevOdString;
    }

    public void setPocevOdString(String pocevOdString) {
        this.pocevOdString = pocevOdString;
    }

    
    public static ArrayList getRezervacijeByDate(Sala sala, Date date) {
        ArrayList<Rezervacija> rezervacije = null;

        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            con = DB.getConnection();
            stmt = con.createStatement();
            String query = "select * from rezervacija where sid=" + sala.getSid() + " and " +
                    "datum='" + date + "' order by PocevOd asc;";
            rs = stmt.executeQuery(query);
            rezervacije = new ArrayList<Rezervacija>();
            while (rs.next()) {
                

                Rezervacija rezervacija = new Rezervacija();
                rezervacija.setRid(rs.getInt("rid"));
                rezervacija.setSala(sala);
                Korisnik kor = DB.getKorisnik(rs.getInt("korisnik"));
                rezervacija.setKorisnik(kor);
                rezervacija.setNamena(rs.getString("namena"));
                rezervacija.setDatum(date);
                rezervacija.setDatumRezervisanja(rs.getTimestamp("datumRezervisanja"));
                rezervacija.setPocevOd(rs.getTime("PocevOd"));
                rezervacija.setTrajanje(rs.getInt("Trajanje"));

                rezervacije.add(rezervacija);
            }

            stmt.close();
            con.close();
        } catch(SQLException sqle) {
            sqle.printStackTrace();
            if (con != null) {
                try {
                    con.close();
                } catch (Exception exc) {
                }
            }
        }

        return rezervacije;
    }
    public ArrayList getRezervacijeByKorisnik() {
        FacesContext context = FacesContext.getCurrentInstance();
        HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
        Korisnik kor = (Korisnik) session.getAttribute("korisnik");

        return getRezervacijeByKorisnikParam(kor);

    }
    public ArrayList getRezervacijeByKorisnikParam(Korisnik kor) {
        
        String query = "select * from rezervacija where korisnik = " + kor.getKid() + " order by datum desc, PocevOd asc;";

        return getRezervacijeByUpit(query);
    }
    public ArrayList getRezervacijeByUpit(String query) {
        ArrayList<Rezervacija> rezervacije = null;

        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            con = DB.getConnection();
            stmt = con.createStatement();
            rs = stmt.executeQuery(query);
            rezervacije = new ArrayList<Rezervacija>();
            while (rs.next()) {


                Rezervacija rezervacija = new Rezervacija();
                rezervacija.setRid(rs.getInt("rid"));
                Sala sa = DB.getSala(rs.getInt("sid"));
                rezervacija.setSala(sa);
                Korisnik kor = DB.getKorisnik(rs.getInt("korisnik"));
                rezervacija.setKorisnik(kor);
                rezervacija.setNamena(rs.getString("namena"));
                rezervacija.setDatum(rs.getDate("datum"));
                rezervacija.setDatumRezervisanja(rs.getTimestamp("datumRezervisanja"));
                rezervacija.setPocevOd(rs.getTime("PocevOd"));
                rezervacija.setTrajanje(rs.getInt("Trajanje"));

                rezervacije.add(rezervacija);
            }

            stmt.close();
            con.close();
        } catch (SQLException sqle) {
            sqle.printStackTrace();
            if (con != null) {
                try {
                    con.close();
                } catch (Exception exc) {
                }
            }
        }

        return rezervacije;
    }

    public String rezervisi() {
        String result = null;
        FacesContext context = FacesContext.getCurrentInstance();
        HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
        Korisnik kor = (Korisnik) session.getAttribute("korisnik");
        Termin ter = kor.getTermin();

        try {
            SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy.");
            setDatum(new Date(dateFormatter.parse(datumString).getTime()));

            SimpleDateFormat timeFormatter = new SimpleDateFormat("H:mm");
            setPocevOd(new Time(timeFormatter.parse(pocevOdString).getTime()));
  
        } catch (ParseException ex) {
            Logger.getLogger(Rezervacija.class.getName()).log(Level.SEVERE, null, ex);
        }
       

        setDatumRezervisanja(new Timestamp(System.currentTimeMillis()));
        if(kor.getIzabraniKorisnik() != null) {
            setKorisnik(kor.getIzabraniKorisnik());
        } else {
            setKorisnik(kor);
        }
        setSala(kor.getIzabrana());

        Calendar tmpCal = new GregorianCalendar();
        tmpCal.setTimeInMillis(pocevOd.getTime());
        tmpCal.set(0, 0, 0);
        tmpCal.set(Calendar.MINUTE, 0);
        tmpCal.set(Calendar.MILLISECOND, 0);
        setPocevOd(new Time(tmpCal.getTimeInMillis()));
        tmpCal.set(Calendar.HOUR_OF_DAY, tmpCal.get(Calendar.HOUR_OF_DAY) + trajanje);
        Time kraj = new Time(tmpCal.getTimeInMillis());

        List<Rezervacija> rezervacije = getRezervacijeByDate(sala, datum);
        boolean zauzet = false;
        for(Rezervacija r:rezervacije) {
            Calendar tmpCal2 = new GregorianCalendar();
            tmpCal2.setTimeInMillis(r.getPocevOd().getTime());
            tmpCal2.set(0, 0, 0);
            tmpCal2.set(Calendar.MINUTE, 0);
            tmpCal2.set(Calendar.MILLISECOND, 0);
            r.setPocevOd(new Time(tmpCal2.getTimeInMillis()));
            tmpCal2.set(Calendar.HOUR_OF_DAY, tmpCal2.get(Calendar.HOUR_OF_DAY) + r.getTrajanje());
            Time kraj2 = new Time(tmpCal2.getTimeInMillis());

            boolean pocetakJednak = pocevOd.equals(r.getPocevOd());
            boolean pocetakUIntervalu = pocevOd.after(r.getPocevOd()) &&  pocevOd.before(kraj2);
            boolean krajJednak = kraj.equals(kraj2);
            boolean krajUIntervalu = kraj.after(r.getPocevOd()) && kraj.before(kraj2);
            boolean obuhvata = pocevOd.before(r.pocevOd) && kraj.after(kraj2);

            if(pocetakJednak || pocetakUIntervalu || krajJednak || krajUIntervalu || obuhvata) {
                zauzet = true;
            }
        }

        Calendar tmpCal3 = new GregorianCalendar();
        tmpCal3.setTimeInMillis(pocevOd.getTime());
        tmpCal3.set(0, 0, 0);
        tmpCal3.set(Calendar.MINUTE, 0);
        tmpCal3.set(Calendar.MILLISECOND, 0);

        int poc = tmpCal3.get(Calendar.HOUR_OF_DAY);

        NeradniDan nd = NeradniDan.getDatumNeradan(sala, new java.util.Date(datum.getTime()));

        if(poc < 8 || poc+trajanje > 22) {
            result = "Izabrani termin prekoračuje radno vreme (od 8 do 22h). Molimo, izaberite termin u okviru radnog vremena.";
        } else if(zauzet) {
            result = "Izabrani termin se preklapa sa već postojećim terminom. Molimo, izaberite drugi termin ili drugu salu.";
        } else if(nd != null) {
            result = "Izabrani termin se nalazi u neradnom danu ("+nd.getRazlog()+"). Molimo, izaberite drugi termin.";
        } else {
            result = saveRezervacija(this);
        }

        
        context.addMessage(null, new FacesMessage(result));
        
        
        return kor.isIsAdmin() ? Korisnik.ACTION_ADMIN : Korisnik.ACTION_KORISNIK;
    }

    public String saveRezervacija(Rezervacija rezervacija) {
        String result = null;
        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            con = DB.getConnection();
            stmt = con.createStatement();
            String query = "insert into rezervacija(sid, korisnik, namena, datum, datumRezervisanja, PocevOd, Trajanje)" +
                    "values (" + rezervacija.getSala().getSid() + ", "
                    + rezervacija.getKorisnik().getKid() + ", "
                    + "'" + rezervacija.getNamena() + "', "
                    + "'" + rezervacija.datum + "', "
                    + "'" + rezervacija.getDatumRezervisanja() + "', "
                    + "'" + rezervacija.getPocevOd() + "', "
                    + rezervacija.getTrajanje() + ");";

            Integer newRid =  stmt.executeUpdate(query);
            if (newRid != null) {
                rezervacija.setRid(newRid);
                result = "Rezervacija uspešno završena!";
            } else {
                result = "Rezervacija nije uspela!";
            }

            stmt.close();
            con.close();
        } catch(SQLException sqle) {
            sqle.printStackTrace();
            if (con != null) {
                try {
                    con.close();
                } catch (Exception exc) {
                }
            }
        }

        return result;
    }

    public String otkazi() {
        String result = null;
        Connection con = null;
        Statement stmt = null;
        ResultSet rs = null;
        FacesContext context = FacesContext.getCurrentInstance();

        try {
            con = DB.getConnection();
            stmt = con.createStatement();
            String query = "delete from rezervacija where rid = " + rid + ";";
            Integer res = stmt.executeUpdate(query);

            if (res == 1) {
                context.addMessage(null, new FacesMessage("Rezervacija uspešno otkazana!"));
            }

            stmt.close();
            con.close();
        } catch(SQLException sqle) {
            sqle.printStackTrace();
            if (con != null) {
                try {
                    con.close();
                } catch (Exception exc) {
                }
            }
        }

        return result;
    }
    
}
